/*
 *  Copyright (c) 2019 by flomesh.io
 *
 *  Unless prior written consent has been obtained from the copyright
 *  owner, the following shall not be allowed.
 *
 *  1. The distribution of any source codes, header files, make files,
 *     or libraries of the software.
 *
 *  2. Disclosure of any source codes pertaining to the software to any
 *     additional parties.
 *
 *  3. Alteration or removal of any notices in or on the software or
 *     within the documentation included within the software.
 *
 *  ALL SOURCE CODE AS WELL AS ALL DOCUMENTATION INCLUDED WITH THIS
 *  SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION, WITHOUT WARRANTY OF ANY
 *  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef KMP_HPP
#define KMP_HPP

#include "data.hpp"

namespace pipy {

//
// KMP
//

class KMP :
  public pjs::RefCount<KMP>,
  public pjs::Pooled<KMP>
{
public:
  KMP(const char *pattern, size_t len);
  ~KMP();

  //
  // KMP::Split
  //

  class Split : public pjs::Pooled<Split> {
  public:
    void input(Data &data);
    void end();

  private:
    Split(KMP *kmp, const std::function<void(Data*)> &output)
      : m_kmp(kmp)
      , m_output(output) {}

    KMP* m_kmp;
    std::function<void(Data*)> m_output;
    Data m_buffer;
    int m_match_len = 0;

    friend class KMP;
  };

  auto split(const std::function<void(Data*)> &output) -> Split*;

private:
  pjs::PooledArray<char>* m_pattern;
  pjs::PooledArray<int>* m_lps_table;
};

} // namespace pipy

#endif // KMP_HPP
